Kriging Module

History

current version 1.0 - 1st July 2018

version date comment
1.0 01/Jul/2018 Original code

License

license: GNU GPL http://www.gnu.org/licenses/

Module Description

routines to implement Kriging interpolation. Firstly the semivariogram is generated from a given sample. The sample point pairs are ordered into even-width bin, separated by the euclidean distance of the point pairs. The Semivariance in the bin is calculated by the Matheron estimator. If number of lags and lag max distance are not given they are automatically computed or set to default value.
Empirical semivariogram is then automatically fitted to the best fitting model among Spherical, Exponential, Gaussian, and Power, considering the nugget effect. Fitting algorithm is adapted from the VARFIT model by Pardo-Iguzquiza (1999). The VARFIT algorithm performs a nonlinear minimization of the weighed squared differences between the experimental variogram and the model. The weighting function is the inverse of the estimation variance. VARFIT uses a non-linear minimisation method that does not require (explicit) initial values for the parameters in order to initialise the minimisation al- gorithm. Jian et al. (1996) report problems with con- vergence if the initial guess is poor. Solution is found with the simplex method of function minimization of Nelder and Mead (1965) This ingenious method is efficient for non-linear mini- mization in a multiparameter space but is still easy to program and only requires evaluations of the objective function. The program stops the iterations whenever one of the two following criteria is reached: 1. Convergence is reached 2. The maximum number of iterations is reached. The best fitted semivariogram model is used to interpolate a regular grid of data. Code is adapted from the Geostats program written by Luke Spadavecchia, Biosphere Atmosphere Modelling Group, University of Edinburgh, November 2006. A number of closest points are used to buils the covariance matrix used to predict value at location where value is unknown. Matrix inversion uses the the Gauss-Jordan method. An n*2,n work array is assembled, with the array of interest on the left half, and the identity matrix on the right half. A check is made to ensure the matrix is invertable, and the matrix inverse is returned, providing the matrix is not singular. The matrix is invertable if, after pivoting and row reduction, the identity matrix shifts to the left half of the work array.

References:

Pardo-Iguzquiza, E. VARFIT: a fortran-77 program for fitting variogram models by weighted least squares. Computers & Geosciences, 25, 251-261, 1999.

Nelder, J.A., Mead, R., 1965. A simplex method for function minimization. Computer Journal 7, 308-313.

Jian, X., Olea, R.A., Yu, Y., 1996. Semivariogram modelling by weighted least squares. Computers & Geosciences 22 (3), 387-397.



Variables

Type Visibility Attributes Name Initial
integer, public, parameter :: AUTOFIT = 5

automatic fitting among spherical, exponential and gaussian

integer, public, parameter :: EXPONENTIAL = 2

fit exponential semivariogram model

integer, public, parameter :: GAUSSIAN = 3

fit gaussian semivariogram model

integer, public, parameter :: POWER = 4

fit power semivariogram model

integer, public, parameter :: SPHERICAL = 1

fit spherical semivariogram model

type(pairs), public, DIMENSION (:,:), ALLOCATABLE :: hobs
real(kind=float), private :: anisotropyAngle

anisotropy angle

real(kind=float), private :: anisotropyRatio

anisotropy ratio >= 1

type(site), private, DIMENSION (:), ALLOCATABLE :: controlpts

subset of closest points used for interpolation

real(kind=float), private, DIMENSION (:), ALLOCATABLE :: cvest
real(kind=float), private, DIMENSION (:,:), ALLOCATABLE :: cvobs
real(kind=float), private, ALLOCATABLE :: dir(:)

angle (radians) between the direction of the variogram and the x axis, measured from the x axis anti-clockwise

real(kind=float), private, ALLOCATABLE :: dir_pairs(:,:)

direction angle between pairs

real(kind=float), private, ALLOCATABLE :: dist(:,:)

average distance for each direction and lag RIMETTERE PRIVATE

real(kind=float), private, ALLOCATABLE :: dist_pairs(:,:)

distance between pairs

real(kind=float), private, ALLOCATABLE :: empVariogram(:,:)

experimental (empirical) variogram for each direction and lag !RIMETTERE PRIVATE

real(kind=float), private :: expVar

experimental variance

real(kind=float), private, DIMENSION (:), ALLOCATABLE :: hest
real(kind=float), private :: hfina

value of the objective function at the minimum

integer(kind=short), private :: ieva
integer(kind=short), private :: ipara

number of parameters to estimate

integer(kind=short), private, ALLOCATABLE :: lagNumber(:)

number of lags for each direction

real(kind=float), private :: lagTolerance(4)

How much the distance between pairs can differ from the exact lag distance and still be included in the lag calculations (m)

integer(kind=short), private, DIMENSION(:), ALLOCATABLE :: last
integer(kind=short), private :: minpairs = 30

minimum number of pairs in the lag to be considered valid for semivariogram fitting.

real(kind=float), private, ALLOCATABLE :: modVariogram(:,:)

modelled (empirical) variogram for each direction and lag !RIMETTERE PRIVATE

integer(kind=short), private :: ndir

number of directions of the variogram

integer(kind=short), private :: npep
real(kind=float), private :: nugget

nugget effect (C0)

integer(kind=short), private :: nvar
integer(kind=short), private :: objectiveFunction

kind of objective function to minimize

type(pairs), private, DIMENSION (:,:), ALLOCATABLE :: obsdist

distance matrix

integer(kind=short), private, ALLOCATABLE :: pairNumber(:,:)

number of pairs for each direction and lag

real(kind=float), private :: parRangeMax(5)

maximum values of parameters

real(kind=float), private :: parRangeMin(5)

minimum values of parameters

real(kind=float), private :: partialSill

partial sill (C1) sill of the variogram

real(kind=float), private :: range

range

real(kind=float), private :: var

variance

real(kind=float), private, DIMENSION (:), ALLOCATABLE :: weights

Derived Types

type, private ::  pairs

Components

Type Visibility Attributes Name Initial
real(kind=float), public :: h

pair distance

integer(kind=short), public :: p1

id of points pair

integer(kind=short), public :: p2

id of points pair

real(kind=float), public :: theta

pair angle

type, private ::  site

Components

Type Visibility Attributes Name Initial
real(kind=float), public :: h

distance (m)

integer(kind=short), public :: oid

identification code

real(kind=float), public :: theta

anistropy angle

real(kind=float), public :: value

observed value

type(Coordinate), public :: xyz

position


Functions

private function Fconv(b, ipara)

function called by Simplex

Arguments

Type IntentOptional Attributes Name
real(kind=float), intent(in) :: b(:)
integer(kind=short), intent(in) :: ipara

Return Value real

private function Valf(a, varmodel)

function called by Simplex

Arguments

Type IntentOptional Attributes Name
real(kind=float), intent(in) :: a(:)
integer(kind=short), intent(in) :: varmodel

Return Value real


Subroutines

public subroutine Krige(sitedata, anisotropy, nlags, maxlag, neighbors, varModel, grid, gridvar, points, predictions, predictionsVar)

Interpolate irregularly spaced data using Kriging. The subroutine generates an empirical semivariogram (anisotropy is assumed), fits the best model among spherical, exponential and gaussian.

Read more…

Arguments

Type IntentOptional Attributes Name
type(ObservationalNetwork), intent(in) :: sitedata
integer(kind=short), intent(in) :: anisotropy

if = 1, anisotropy is considered

integer(kind=short), intent(in) :: nlags

the number of discrete distances used for comparing data, if 0 it is set to default value

real(kind=float), intent(in) :: maxlag

maximum distance to consider for semivariogram assessment (m), if 0 it is automatically computed

integer(kind=short), intent(in) :: neighbors

number of neighbors to consider for interpolation

integer(kind=short), intent(in) :: varModel

semivariogram model, autofit for atomatic selecting the best among spherical, exponential, and gaussian

type(grid_real), intent(inout), optional :: grid

interpolated grid

type(grid_real), intent(inout), optional :: gridvar

variance of interpolated grid

type(Coordinate), intent(in), optional :: points(:)

list of coordinates for prediction (alternative to regular grid)

real(kind=float), intent(inout), optional, DIMENSION (:) :: predictions
real(kind=float), intent(inout), optional, DIMENSION (:) :: predictionsVar

public subroutine Matinv(input, output)

A generic subroutine to invert a square 2D matrix by pivoting ("Gauss-Jordan" method). An n*2,n work array is assembled, with the array of interest on the left half, and the identity matrix on the right half. A check is made to ensure the matrix is invertable, and the matrix inverse is returned, providing the matrix is not singular. The matrix is invertable if, after pivoting and row reduction, the identity matrix shifts to the left half of the work array. Initially the code was written in integer form to avoid fractions in the work array, but numbers rapidly become inconcevably large. The implemented solution therefore works on fractional pivot rows, with pivots factored to leading ones. Double precision arrays have been used to maintain numerical stability.

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=float), intent(in), DIMENSION(:,:) :: input
real(kind=float), intent(out), DIMENSION(:,:) :: output

public subroutine PairDirection(stations)

Compute direction angle between pairs (radians) measured from the x axis anti-clockwise

Arguments

Type IntentOptional Attributes Name
type(ObservationalNetwork), intent(in) :: stations

private subroutine Covariance(dist, theta, cov, sill, range, varmodel)

Subroutine to calculate a covariance vector from a semivariogram model and a vector of separation distances.

Arguments

Type IntentOptional Attributes Name
real(kind=float), intent(in), DIMENSION(:) :: dist

separation distance vector

real(kind=float), intent(in), DIMENSION(:) :: theta

anisotropy angle ??

real(kind=float), intent(out), DIMENSION(:) :: cov

covariance vector

real(kind=float), intent(in) :: sill

partial sill (total sill - nugget) from automatic fitting

real(kind=float), intent(in) :: range

range from automatic fitting

integer(kind=short), intent(in) :: varmodel

semivariogram model: 1 = spherical, 2 = exponential, 3 = gaussian, 4 = power

private subroutine Covariance2D(dist, theta, cov, sill, range, varmodel)

Subroutine to calculate a covariance matrix of observations from a semivariogram model and a vector of separation distances.

Arguments

Type IntentOptional Attributes Name
real(kind=float), intent(in), DIMENSION(:,:) :: dist

separation distance vector

real(kind=float), intent(in), DIMENSION(:,:) :: theta

anisotropy angle ??

real(kind=float), intent(out), DIMENSION(:,:) :: cov

covariance matrix

real(kind=float), intent(in) :: sill

partial sill (total sill - nugget) from automatic fitting

real(kind=float), intent(in) :: range

range from automatic fitting

integer(kind=short), intent(in) :: varmodel

semivariogram model: 1 = spherical, 2 = exponential, 3 = gaussian, 4 = power

private subroutine DistMatrix(stations)

A subroutine to assemble the global distance. This operation is only carried out once; kriging observations matricies are subsetted from this lookup table to speed up processing.

Arguments

Type IntentOptional Attributes Name
type(ObservationalNetwork), intent(in) :: stations

private subroutine Focompu(varmodel, hoo)

evaluation of the objective function

Arguments

Type IntentOptional Attributes Name
integer(kind=short), intent(in) :: varmodel
real(kind=float), intent(out) :: hoo

private subroutine Interpolate(cvobs, cvest, controlpts, est, var, neighbors, sill)

A subroutine to predict the data value of an unsampled location, using geostatistical methods. Interpolation is carried out using the 'Ordinary Kriging' method.

Arguments

Type IntentOptional Attributes Name
real(kind=float), intent(in), DIMENSION(:,:) :: cvobs
real(kind=float), intent(in), DIMENSION(:) :: cvest
real(kind=float), intent(in), DIMENSION(:) :: controlpts
real(kind=float), intent(out) :: est

estimated value

real(kind=float), intent(out) :: var

variance of estimated value

integer(kind=short), intent(in) :: neighbors
real(kind=float), intent(in) :: sill

private subroutine KrigingInitialize(anisotropy, nlags, maxlag, count, neighbors, nclosest)

Initialize variables for kriging

Arguments

Type IntentOptional Attributes Name
integer(kind=short), intent(in) :: anisotropy

if = 1, anisotropy is considered

integer(kind=short), intent(in) :: nlags

the number of discrete distances used for comparing data, if 0 it is set to default value

real(kind=float), intent(in) :: maxlag

maximum distance to consider for semivariogram assessment (m), if 0 it is automatically computed

integer(kind=short), intent(in) :: count

total number of available observations

integer(kind=short), intent(in) :: neighbors

number of neighbors to consider for interpolation

integer(kind=short), intent(out) :: nclosest

private subroutine PairDistance(stations)

Compute distance between pairs

Arguments

Type IntentOptional Attributes Name
type(ObservationalNetwork), intent(in) :: stations

private subroutine Semivariogram(stations)

generate a Semivariogram from a given sample. The sample point pairs are ordered into even-width bin, separated by the euclidean distance of the point pairs. The Semivariance in the bin is calculated by the Matheron estimator. If number of lags and lag max distance are not given they are automatically computed or set to default value.

Read more…

Arguments

Type IntentOptional Attributes Name
type(ObservationalNetwork), intent(in) :: stations

private subroutine Separation(prediction, observations, estdist)

Subroutine to find the distances between prediction point and observations. Also returns angles if anisotropy present

Arguments

Type IntentOptional Attributes Name
type(site), intent(in) :: prediction
type(ObservationalNetwork), intent(in) :: observations
type(site), intent(out), DIMENSION(:) :: estdist

private subroutine Simplex(varModel)

This subroutine implements the simplex method of function minimization of Nelder and Mead (1965). This ingenious method is efficient for non-linear mini- mization in a multiparameter space but is still easy to program and only requires evaluations of the objective function. The program stops the iterations whenever one of the two following criteria is reached: 1. Convergence is reached 2. The maximum number of iterations is reached.

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=short), intent(in) :: varModel

type of variogram: 1 = spherical, 2 = exponential, 3 = gaussian, 4 = power

private subroutine Sort(input, flag)

Subroutine to sort a vector of points using the Heap-sort algorithm. Data are sorted by value if flag =1, or by separation distance if flag = 0. Actually, only a pointer is sorted, as this is more efficient. Subroutine Adapted from Numerical Recipes in Fortran 90: Press, Teukolsky, Vetterling and Flannery (1996) pg. 1171

Arguments

Type IntentOptional Attributes Name
type(site), intent(inout), DIMENSION(:) :: input
integer, intent(in) :: flag

private subroutine Sorted(estdist, neighbors)

A subroutine to retrieve the nearest neighbors of the estimation location referred to as control points. The observations separation matrix is returned (as a precursor to producing the observations covariance matrix) along with the vector of nearest neighbbors.

Arguments

Type IntentOptional Attributes Name
type(site), intent(inout), DIMENSION(:) :: estdist
integer(kind=short), intent(in) :: neighbors

private subroutine Varfit(varModel, modelselected)

Fit model to experimental variogram

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=short), intent(in) :: varModel
integer(kind=short), intent(out) :: modelselected

if automodel is passed as varModel, the optimal model is returned

private subroutine Variogr(varmodel, h, alpha, gam)

calculation of the variogram value in 2D

Arguments

Type IntentOptional Attributes Name
integer(kind=short), intent(in) :: varmodel
real(kind=float), intent(inout) :: h
real(kind=float), intent(in) :: alpha
real(kind=float), intent(out) :: gam